﻿using System;
using System.Collections.Generic;
using System.Web;
using System.IO;


namespace CCPSIP.Sticker
{
    /// <summary>CCPSIP_034：下載機器人貼圖檔案 API</summary>
    /// idHeader = 裝置 UUID 前八碼。
    /// checkcode = 裝置限時驗證碼。
    /// ROBOT_ID = 機器人ID。
    /// DirName = 資料夾名稱。
    /// FileName = 檔案名稱。

    public class robot_sticker_get : IHttpHandler
    {
        private const string kStickerDirRobot = @"\\203.69.132.77\Sip-Line\Robot";
        private const long kMaxFileLength = 5 * 1048576;// 5MB


        public void ProcessRequest(HttpContext context)
        {
            HttpRequest req = context.Request;
            HttpResponse resp = context.Response;
            resp.ContentType = "text/plain";
            resp.ContentEncoding = System.Text.Encoding.UTF8;
            DateTime reqTime = DateTime.Now;

            try
            {
                //【01】取得POST參數，驗證身分
                //
                string idHeader = req.Form["idHeader"];
                string checkcode = req.Form["checkcode"];
                string ROBOT_ID = req.Form["ROBOT_ID"];//機器人ID
                string DirName = req.Form["DirName"];  //資料夾名稱
                string FileName = req.Form["FileName"];//檔案名稱

                SipUserInfo userInfo = SipKit.GetUserInfo(idHeader, checkcode, req);
                if (userInfo == null)
                {
                    throw new Exception("Error_01: Cannot identify this device");//無法識別此裝置
                }


                //【02】檢查檔案路徑問題(防路徑攻擊)
                //
                if (DirName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
                {
                    throw new Exception("Error_02: Directory Name Error");//資料夾名稱錯誤
                }
                else if (FileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
                {
                    throw new Exception("Error_03: File Name Error");//檔案名稱錯誤
                }


                //【03】檢查機器人權限
                //
                List<string> robotIDs = new List<string>();
                RobotInfo[] robots = RobotKit.getRobots(userInfo);
                foreach (RobotInfo robot in robots)
                {
                    robotIDs.Add(robot.ROBOT_ID);
                }
                if (!robotIDs.Contains(ROBOT_ID))
                {
                    throw new Exception("Error_04: You have no right to use this robot");//無機器人權限
                }


                //【04】組合檔案路徑
                //
                string stickerPath = string.Format(@"{0}\{1}\{2}\{3}", kStickerDirRobot, ROBOT_ID, DirName, FileName);


                //【05】切換網域身分存取資料夾
                //
                string tempCode = HashKit.getHashStr("CCPSIP-20121030", HashType.SHA512).Substring(6, 20);

                using (new Tools.Impersonator("iSIPAgent", "CCP.COM.TW", tempCode))
                {
                    if (!File.Exists(stickerPath))
                    {
                        throw new Exception("Error_05: File not found");//檔案不存在
                    }

                    FileInfo fInfo = new FileInfo(stickerPath);
                    if (fInfo.Length > kMaxFileLength)
                    {
                        throw new Exception("Error_06: File size exceeds limit");//檔案大小超過上限
                    }

                    //【99】回傳HTTP Header與圖片檔案
                    // http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
                    //
                    resp.ContentType = "image/png";
                    resp.AppendHeader("Content-Length", fInfo.Length.ToString());
                    resp.AppendHeader("Last-Modified", fInfo.LastWriteTime.ToUniversalTime().ToString("r"));
                    resp.AppendHeader("Content-Disposition", ChrisKit.getContentDisposition(FileName));
                    resp.AppendHeader("Cache-Control", "no-cache");

                    if (fInfo.Length >= 4 * 1048576)
                        resp.TransmitFile(stickerPath);//Large File
                    else
                        resp.WriteFile(stickerPath, true);//Small File
                }
            }
            catch (Exception ex)
            {
                resp.ContentType = "application/xml";
                string resultStr = ChrisKit.Ex2Xml(ex, false);
                int contentLength = resp.ContentEncoding.GetByteCount(resultStr);
                resp.AppendHeader("Content-Length", contentLength.ToString());
                resp.Write(resultStr);
            }
            finally
            {
                resp.Flush();
                resp.Close();
            }
        }


        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

    }
}
